package com.jnchen.jwt.impl;

import com.jnchen.jwt.api.JwtInterface;
import com.jnchen.jwt.entity.User;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;

import java.util.List;

/**
 * jose4j 实现
 *
 * @author jnchen
 * @date 2020/10/30 09:56
 */
public class Jose4jImpl implements JwtInterface {
    private static RsaJsonWebKey key;

    static {
        try {
            key = RsaJwkGenerator.generateJwk(2048);
        } catch (JoseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String createJwt(User user, long expireIn) {
        try {
            JwtClaims claims = new JwtClaims();
            claims.setClaim("id", user.getId());
            claims.setClaim("name", user.getName());
            claims.setClaim("operations", user.getOperations());
            claims.setExpirationTimeMinutesInTheFuture((float) (expireIn / 1000.0 / 60.0));
            JsonWebSignature signature = new JsonWebSignature();
            signature.setPayload(claims.toJson());
            signature.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
            signature.setKey(key.getPrivateKey());
            return signature.getCompactSerialization();
        } catch (JoseException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public User parseJwt(String token) {
        try {
            JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime()
                    .setVerificationKey(key.getKey()).build();

            JwtClaims claims = jwtConsumer.processToClaims(token);
            User user = new User();
            user.setId(claims.getClaimValue("id", Long.class).intValue());
            user.setName(claims.getClaimValue("name", String.class));
            user.setOperations(claims.getClaimValue("operations", List.class));
            return user;
        } catch (MalformedClaimException | InvalidJwtException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    @SuppressWarnings("unused")
    public boolean checkJwt(String token) {
        try {
            JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime()
                    .setVerificationKey(key.getKey()).build();
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}
